package com.apes.hr.group.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.apes.framework.api.DomainService;
import com.apes.framework.jpa.logger.ApesLoggerService;
import com.apes.framework.jpa.spec.JpaDsl;
import com.apes.framework.plugin.esb.api.SimpleRequest;
import com.apes.framework.plugin.outbox.OutboxPayloadWrapper;
import com.apes.framework.plugin.outbox.annotation.OutboxSubscriber;
import com.apes.framework.util.MapUtil;
import com.apes.hr.base.model.Employee;
import com.apes.hr.base.model.WorkPost;
import com.apes.hr.base.repository.EmployeeRepository;
import com.apes.hr.group.model.*;
import com.apes.hr.group.repository.DingDingDeptRelevanceRepository;
import com.apes.hr.group.repository.DingDingDeptRepository;
import com.apes.hr.group.repository.DingDingGroupPersonRepository;
import com.apes.hr.group.repository.DingDingPersonRepository;
import com.apes.hr.paySupport.model.SupportApplicationItem;
import com.apes.hr.paySupport.repository.SupportApplicationItemRepository;
import com.apes.hr.recruit.model.ApplyJobOrder;
import com.apes.hr.recruit.repository.ApplyJobOrderRepository;
import com.apes.hr.thirdParty.dingidng.model.DingDingToken;
import com.apes.hr.thirdParty.dingidng.model.SimpleGroupDetail;
import com.apes.hr.thirdParty.dingidng.repository.SimpleGroupDetailRepository;
import com.apes.hr.thirdParty.dingidng.service.DingDingService;
import com.apes.hr.transfer.model.TransferApplicationItem;
import com.apes.hr.transfer.service.TransferApplicationItemService;
import com.apes.scm.masterdata.enumeration.model.Enumeration;
import com.apes.scm.masterdata.frame.model.Branch;
import com.apes.scm.masterdata.frame.model.BranchEntry;
import com.apes.scm.masterdata.frame.repository.BranchRepository;
import com.apes.scm.masterdata.party.model.PartyRole;
import com.apes.scm.rbac.model.Post;
import com.apes.scm.rbac.model.User;
import com.apes.scm.rbac.repository.PostRepository;
import com.dingtalk.api.DefaultDingTalkClient;
import com.dingtalk.api.DingTalkClient;
import com.dingtalk.api.request.*;
import com.dingtalk.api.response.*;
import com.taobao.api.ApiException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 功能：部门群组表
 *
 * @author ZhengZX
 * @create 2020年9月10日10:50:21
 */
@Service("hrDingDingDeptService")
@SuppressWarnings("all")
public class DingDingDeptService extends DomainService {

    @Autowired
    DingDingToken dingDingToken;
    @Autowired
    DingDingDeptRepository dingDingDeptRepository;
    @Autowired
    private DingDingService dingService;
    @Autowired
    DingDingService dingDingService;
    @Autowired
    DingDingDeptRelevanceRepository dingDingDeptRelevanceRepository;
    @Autowired
    BranchRepository branchRepository;
    @Autowired
    public TransferApplicationItemService itemService;
    @Autowired
    public DingDingGroupPersonRepository dingDingGroupPersonRepository;
    @Autowired
    PostRepository postRepository;
    @Autowired
    EmployeeRepository employeeRepository;
    @Autowired
    ApplyJobOrderRepository applyJobOrderRepository;
    @Autowired
    DingDingPersonRepository dingDingPersonRepository;
    @Autowired
    SimpleGroupDetailRepository simpleGroupDetailRepository;
    @Autowired
    ApesLoggerService apesLoggerService;
    @Autowired
    SupportApplicationItemRepository supportApplicationItemRepository;

    //定时获取钉钉部门信息
    public void getDeptList(SimpleRequest simpleRequest) throws ApiException{
        DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/department/list");
        OapiDepartmentListRequest request = new OapiDepartmentListRequest();
        request.setId("1");
        request.setFetchChild(true);
        request.setHttpMethod("GET");
        OapiDepartmentListResponse response = client.execute(request, dingDingToken.getAccessToken());
        List<OapiDepartmentListResponse.Department> department = response.getDepartment();  //获取钉钉所有的部门
        for (OapiDepartmentListResponse.Department item : department) {
            DingDingDept dingDingDept = dingDingDeptRepository.findOne(String.valueOf(item.getId()));

            if ( dingDingDept == null) {
                dingDingDept = new DingDingDept();
                dingDingDept.setId(String.valueOf(item.getId()));
            }

            dingDingDept.setName(item.getName());               //部门名称
            dingDingDept.setParentId(String.valueOf(item.getParentid()));   //父部门ID
            dingDingDept.setAutoAddUser(item.getAutoAddUser()); //自动加群
            dingDingDept.setCreateDeptGroup(item.getCreateDeptGroup()); //是否建群
            DingDingDept deptDetail = getDeptDetail(String.valueOf(item.getId()), dingDingToken.getAccessToken());//查询详细信息
            dingDingDept.setDeptManagerUseridList(deptDetail.getDeptManagerUseridList());   //主管
            dingDingDept.setOrgDeptOwner(deptDetail.getOrgDeptOwner()); //群主
            dingDingDept.setGroupName(item.getName());  //设置群名
            dingDingDeptRepository.saveAndFlush(dingDingDept);
        }
    }

    //获取部门详情
    public DingDingDept getDeptDetail(String id,String accessToken) throws ApiException{
        DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/department/get");
        OapiDepartmentGetRequest req = new OapiDepartmentGetRequest();
        req.setId(id);
        req.setHttpMethod("GET");
        OapiDepartmentGetResponse rsp = client.execute(req, accessToken);
        DingDingDept dingDingDept = new DingDingDept();
        dingDingDept.setOrgDeptOwner(rsp.getOrgDeptOwner());    //群主ID
        dingDingDept.setDeptManagerUseridList(rsp.getDeptManagerUseridList());  //主管ID
        return dingDingDept;
    }

    //修改
    public DingDingDept update(SimpleRequest request) throws ApiException{
        DingDingDept dingDingDept = request.getO(DingDingDept.class);
        DingDingDept dingDept = dingDingDeptRepository.findOne(dingDingDept.getId());
        if (dingDept == null) throw new RuntimeException("钉钉部门【" + dingDingDept.getId() + "】在系统中不存在。");
        if (dingDept.getVersion() != dingDingDept.getVersion()) throw new RuntimeException("记录已更新或已删除，请重新提交！");  // 用于判断当前版本是否被修改
        if (dingDingDept.getOrgDeptOwnerTemp()!=null) dingDingDept.setOrgDeptOwner(dingDingDept.getOrgDeptOwnerTemp().getDingDingUserId());
        OapiDepartmentUpdateResponse rsp = updateDept(dingDingDept);
        if (rsp.getErrcode()!=0){
            throw new RuntimeException(rsp.getErrcode()+rsp.getErrmsg());
        }
        dingDingDept = dingDingDeptRepository.saveAndFlush(dingDingDept);
        return dingDingDept;
    }

    //删除
    public String delete(SimpleRequest request) throws ApiException {
        String id = request.get("id");
        long versions = (int) request.get("version"); // 获取当前请求的版本信息
        DingDingDept dingDept = dingDingDeptRepository.findOne(id);
        if (dingDept == null) throw new RuntimeException("钉钉部门【" + id + "】在系统中不存在。");
        if (dingDept.getVersion() != versions) throw new RuntimeException("记录已更新或已删除，请重新提交！");  // 用于判断当前版本是否被修改
        DingDingDept dingDingDept = request.getO(DingDingDept.class);
        OapiDepartmentDeleteResponse rsp = deleteDept(id);
        if (rsp.getErrcode()!=0){
            if (rsp.getErrcode()!=60003){    //不拦截部门不存在报错
                throw new RuntimeException(rsp.getErrcode() + rsp.getErrmsg());
            }
        }
        dingDingDeptRepository.delete(dingDingDept);
        return "删除成功！";
    }

    //更新部门（同步钉钉）
    public OapiDepartmentUpdateResponse updateDept(DingDingDept dingDingDept) throws ApiException{
        DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/department/update");
        OapiDepartmentUpdateRequest req = new OapiDepartmentUpdateRequest();
        req.setId(Long.valueOf(dingDingDept.getId()));
        req.setName(dingDingDept.getName());
        req.setParentid(dingDingDept.getParentId());
        req.setOrgDeptOwner(dingDingDept.getOrgDeptOwner());
        req.setDeptManagerUseridList(dingDingDept.getDeptManagerUseridList());
        return client.execute(req, dingDingToken.getAccessToken());
    }

    //删除部门（同步钉钉）
    public OapiDepartmentDeleteResponse deleteDept(String id) throws ApiException{
        DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/department/delete");
        OapiDepartmentDeleteRequest req = new OapiDepartmentDeleteRequest();
        req.setId(id);
        req.setHttpMethod("GET");
        OapiDepartmentDeleteResponse rsp = client.execute(req, dingDingToken.getAccessToken());
        return rsp;
    }

    //保存
    public DingDingDept save(SimpleRequest request) throws ApiException{
        DingDingDept dingDingDept = request.getO(DingDingDept.class);
        DingDingDept tempDingDingDept = dingDingDeptRepository.findByName(dingDingDept.getName());
        OapiDepartmentCreateResponse rsp = saveDept(dingDingDept);
        dingDingDept.setId(String.valueOf(rsp.getId()));
        dingDingDept.setGroupName(dingDingDept.getName());  //设置群名和部门名一致
        dingDingDept.setParentId("1");  //设置父部门为1
        if (dingDingDept.isCreateDeptGroup()){
            List<Long> userDept = getUser("0008");  //查找某个用户所拥有的群
            userDept.add(rsp.getId());
            userUpdate(userDept,"0008");            //更新用户的群组
            updateDeptByQZ(rsp.getId(),"0008");          //将用户设置为群主
        }
        if (tempDingDingDept!=null){
            if (tempDingDingDept.getName().equals(dingDingDept.getName())) throw new RuntimeException("钉钉部门【" + tempDingDingDept.getName() + "】在系统中已存在。");
        }
        dingDingDept = dingDingDeptRepository.saveAndFlush(dingDingDept);
        return dingDingDept;
    }

    /**
     * 保存 （同步部门）
     * @param dingDingDept
     * @return
     * @throws ApiException
     */
    public OapiDepartmentCreateResponse saveDept(DingDingDept dingDingDept) throws ApiException{
        DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/department/create");
        OapiDepartmentCreateRequest req = new OapiDepartmentCreateRequest();
        req.setParentid("1");
        req.setCreateDeptGroup(dingDingDept.isCreateDeptGroup());
        req.setName(dingDingDept.getName());
        OapiDepartmentCreateResponse rsp = client.execute(req, dingDingToken.getAccessToken());
        //60008(父部门下该部门名称已存在)不拦截这个错误状态
        if (rsp.getErrcode()!=0 && rsp.getErrcode()!=60008) throw new RuntimeException("创建钉钉群失败  " + rsp.getErrmsg());
        return rsp;
    }

    /**
     * 开店申请同步钉钉部门和群
     */
    public void passBranchSaveDept(BranchEntry branchEntry) {
        Branch branch = branchRepository.findByOrigin(branchEntry.getCode()); //根据外部ID查找到行政部门
        DingDingDept dingDingDept = new DingDingDept();
        dingDingDept.setBranch(branch);
        dingDingDept.setName(branchEntry.getCode() + branchEntry.getName());//创建的部门名称根据开店申请的编码和部门名称组成
        //开店申请创建的群设置群规则为当前的行政部门(做部门群使用)
        List<DingDingDeptDetail> dingDingDeptDetails = new ArrayList<>();
        DingDingDeptDetail dingDingDeptDetail = new DingDingDeptDetail();
        dingDingDeptDetail.setBranch(branch);
        dingDingDeptDetails.add(dingDingDeptDetail);
        dingDingDept.setDingDingDeptDetails(dingDingDeptDetails);
        try {
            OapiDepartmentCreateResponse rsp = saveDept(dingDingDept);
            //rsp.getId()没有获取到部门ID的情况不进行更新用户和写入钉钉部门操作
            if (rsp.getId() != null){
                dingDingDept.setId(String.valueOf(rsp.getId()));
                dingDingDept.setGroupName(dingDingDept.getName());  //设置群名和部门名一致
                dingDingDept.setParentId("1");  //设置父部门为1
                List<Long> userDept = getUser("0008");  //查找某个用户所拥有的群
                userDept.add(rsp.getId());
                userUpdate(userDept,"0008");            //更新用户的群组
                updateDeptByQZ(rsp.getId(),"0008");          //将用户设置为群主
                groupPerson(rsp.getId());                        //开店申请拉群人员
                if (rsp.getErrcode()!=0) throw new RuntimeException("同步创建钉钉群失败  " + rsp.getErrmsg());
                dingDingDeptRepository.saveAndFlush(dingDingDept);
            }
        } catch (ApiException e) {
            e.printStackTrace();
        }
    }

    /**
     * 开店申请建群拉入人员
     */
    public void groupPerson(Long deptId){
        List<DingDingGroupPerson> list = dingDingGroupPersonRepository.findAll();
        list.stream().forEach(s -> {
            Set<DingDingPerson> groupUserIdSet = s.getGroupUserIdSet();
            groupUserIdSet.forEach(g -> {
                List<Long> userDept = getUser(g.getDingDingUserId());  //查找某个用户所拥有的群
                userDept.add(deptId);   //添加开店申请创建的群ID
                userUpdate(userDept,g.getDingDingUserId());            //更新用户的群组
            });
        });
    }

    /**
     * 更新用户
     * @param list  存放多个群组ID
     * @param userId    需要修改的用户编码
     */
    public void userUpdate(List<Long> list, String userId){
        DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/user/update");
        OapiUserUpdateRequest req = new OapiUserUpdateRequest();
        req.setUserid(userId);
        req.setDepartment(list);
        OapiUserUpdateResponse rsp = null;
        try {
            rsp = client.execute(req, dingDingToken.getAccessToken());
        } catch (ApiException e) {
            e.printStackTrace();
        }
        if (rsp.getErrcode()!=0) throw new RuntimeException("同步用户到钉钉群失败  " + rsp.getErrmsg());
    }

    /**
     *获取用户详情部门列表
     * @param userId
     */
    public List<Long> getUser(String userId){
        DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/user/get");
        OapiUserGetRequest req = new OapiUserGetRequest();
        req.setUserid(userId);
        req.setHttpMethod("GET");
        OapiUserGetResponse rsp = null;
        try {
            rsp = client.execute(req, dingDingToken.getAccessToken());
            if (rsp.getErrcode()!=0) throw new RuntimeException("获取用户详情失败  " + rsp.getErrmsg());
        }catch (ApiException e){
            e.printStackTrace();
        }
        return rsp.getDepartment();
    }

    /**
     * 根据部门对应的主管
     * @param id
     * @return
     */
    public String getZGByDept(String id){
        DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/department/get");
        OapiDepartmentGetRequest req = new OapiDepartmentGetRequest();
        req.setId(id);
        req.setHttpMethod("GET");
        OapiDepartmentGetResponse rsp = null;
        try {
            rsp = client.execute(req, dingDingToken.getAccessToken());
            if (rsp.getErrcode()!=0) throw new RuntimeException("获取部门对应信息失败  " + rsp.getErrmsg());
        } catch (ApiException e) {
            e.printStackTrace();
        }
        return rsp.getDeptManagerUseridList();
    }

    /**
     * 更新部门主管
     * @param id
     * @param zg
     */
    public void updateDeptByZG(Long id,String zg){
        DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/department/update");
        OapiDepartmentUpdateRequest req = new OapiDepartmentUpdateRequest();
        req.setId(id);
        req.setDeptManagerUseridList(zg);
        try {
            OapiDepartmentUpdateResponse rsp = client.execute(req, dingDingToken.getAccessToken());
            if (rsp.getErrcode()!=0) throw new RuntimeException("更新钉钉用户失败  " + rsp.getErrmsg());
        } catch (ApiException e) {
            e.printStackTrace();
        }
    }

    /**
     * 更新部门群主
     * @param id
     * @param qz
     */
    public void updateDeptByQZ(Long id,String qz){
        DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/department/update");
        OapiDepartmentUpdateRequest req = new OapiDepartmentUpdateRequest();
        req.setId(id);
        req.setOrgDeptOwner(qz);
        try {
            OapiDepartmentUpdateResponse rsp = client.execute(req, dingDingToken.getAccessToken());
            if (rsp.getErrcode()!=0) throw new RuntimeException("更新钉钉用户失败  " + rsp.getErrmsg());
        } catch (ApiException e) {
            e.printStackTrace();
        }
    }

    public Boolean getUserValid(String userId){
        DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/user/get");
        OapiUserGetRequest req = new OapiUserGetRequest();
        req.setUserid(userId);
        req.setHttpMethod("GET");
        OapiUserGetResponse rsp = null;
        try {
            rsp = client.execute(req, dingDingToken.getAccessToken());
            if(rsp.getErrcode() == 0) return false;
        } catch (ApiException e) {
            e.printStackTrace();
        }
        return true;
    }

    /**
     * 根据公司部门岗位运营模式维度查找对应相关的钉钉群ID
     * @param operation     //运营模式
     * @param company       //公司
     * @param branch        //行政部门
     * @param workPost      //岗位
     * @return departments 所有的钉钉群号
     */
    public List<Long> getDingDingIds(Enumeration operation,PartyRole company, Branch branch , WorkPost workPost){
        List<Long> departments = new ArrayList();   //存放钉钉群编号

        //根据六种组合方式查找对应的钉钉部门
        List<DingDingDept> dingDingDepts1 = dingDingDeptRepository.findByOpertion(operation.getId());
        List<DingDingDept> dingDingDepts2 = dingDingDeptRepository.findByCompany(company.getId());
        List<DingDingDept> dingDingDepts3 = dingDingDeptRepository.findByBranch(branch.getId());
        List<DingDingDept> dingDingDepts4 = dingDingDeptRepository.findByOperationAndWorkPost(operation.getId(),workPost.getId());
        List<DingDingDept> dingDingDepts5 = dingDingDeptRepository.findByCompanyAndWorkPost(company.getId(),workPost.getId());
        List<DingDingDept> dingDingDepts6 = dingDingDeptRepository.findByBranchAndWorkPost(branch.getId(),workPost.getId());
        List<DingDingDept> dingDingDepts7 = dingDingDeptRepository.findByWorkPost(workPost.getId());

        //添加群ID
        dingDingDepts1.forEach(d -> departments.add(Long.valueOf(d.getId())));
        dingDingDepts2.forEach(d -> departments.add(Long.valueOf(d.getId())));
        dingDingDepts3.forEach(d -> departments.add(Long.valueOf(d.getId())));
        dingDingDepts4.forEach(d -> departments.add(Long.valueOf(d.getId())));
        dingDingDepts5.forEach(d -> departments.add(Long.valueOf(d.getId())));
        dingDingDepts6.forEach(d -> departments.add(Long.valueOf(d.getId())));
        dingDingDepts7.forEach(d -> departments.add(Long.valueOf(d.getId())));

        return departments;
    }

    /**
     * 获取部门群
     * @param branch
     * @return
     */
    public List<Long> getBranchDingDing(Branch branch){
        List<Long> departments = new ArrayList<>();
//        List<DingDingDept> dingDingDepts = dingDingDeptRepository.findAll(   //查询只满足部门维度的群
//                JpaDsl.toCriteria(
//                        "dingDingDeptDetails.company.id","EQ", null,
//                        "dingDingDeptDetails.branch.id","EQ", branch.getId(),
//                        "dingDingDeptDetails.workPost.id","EQ", null,
//                        "dingDingDeptDetails.operation.id","EQ",null
//                )
//        );
        List<DingDingDept> dingDingDepts = dingDingDeptRepository.findByBranch(branch); //根据钉钉部门上的行政部门查找部门群

        dingDingDepts.forEach(d -> departments.add(Long.valueOf(d.getId())));
        return departments;
    }

    /**
     * 根据人员信息获取钉钉ID
     * @param employee 人员信息
     * @return 钉钉ID
     */
    public DingDingPerson getDingDingUserId(Employee employee){
        DingDingPerson dingDingPerson = dingDingPersonRepository.findByEmployee(employee);
//        String dingDingUserId = null;
//        if (dingDingPerson!=null){
//            dingDingUserId = dingDingPerson.getDingDingUserId();
//        }
        if (dingDingPerson == null) throw new RuntimeException("系统上没有" + employee.getName() + "的钉钉ID，请检查！！！");
        return dingDingPerson;
    }

    @OutboxSubscriber(name = "开店申请创建钉钉群")
    public void branchEntryCreateDingDing(BranchEntry branchEntry) {
        if (branchEntry.getState().equals("approve")){
            if (branchEntry.isAutoFound()){ //选择了自动建群
                passBranchSaveDept(branchEntry);    //使用开店部门相关信息创建群和对应规则信息
            }
        }
    }

    @OutboxSubscriber(name = "执行离职操作")
    public void leaveDingDing(User user) {
//        if (!quitJobOrder.getState().equals("confirm")) return;
//        DingDingPerson dingDingPerson = dingDingPersonRepository.findByEmployee(quitJobOrder.getEmployee());
//        if (dingDingPerson == null){
//            throw new RuntimeException(quitJobOrder.getEmployee().getName() + " 未查询到对应的钉钉ID无法删除钉钉请检查！！！");
//        }
//        if (dingDingPerson != null) {
//            if (dingDingPerson.isExecute()) return; //判断执行标识，已执行过的不作执行
//            deleteDingDingUser(dingDingPerson.getDingDingUserId());//离职删除钉钉用户
//            dingDingPerson.setExecute(true);    //更新标识为已删除
//            dingDingPersonRepository.saveAndFlush(dingDingPerson);

        if(user.isDisable()){
            //操作员被禁用就删除钉钉
            Employee employee = employeeRepository.findByOrigin(user.getOrigin());
            if (employee!=null){
                if (employee.getEmployeeState().getId().equals("000089")){  //人员档案状态为离职
                    DingDingPerson dingDingPerson = dingDingPersonRepository.findByEmployee(employee);  //获取钉钉ID
                    if (dingDingPerson!=null){
                        deleteDingDingUser(dingDingPerson.getDingDingUserId());
                        //写入日志
                        apesLoggerService.sendSynEvent("event:ir.logger.create", MapUtil.mapper("businessType", "DingDingPerson",
                                "businessKey", dingDingPerson.getDingDingUserId(), "operate", "离职申请单删除人员钉钉", "workPostName",null ,"operator_id", 1));
                    }
                }
            }
        }
    }

    @OutboxSubscriber(id = "local:hrDingDingDeptService.doneDingDing", name = "入职申请单确认入职，调整钉钉群和考勤组")
    public void doneDingDing(OutboxPayloadWrapper outboxPayloadWrapper) {
        JSONObject object = JSONObject.parseObject(outboxPayloadWrapper.getPayload());
        ApplyJobOrder applyJobOrder = applyJobOrderRepository.findOne(object.getString("id"));
        //入职成功后 获取对应的钉钉群ID
        List<Long> list = getDingDingIds(applyJobOrder.getCompany().getParty().getCorporate().getOperation(),
                applyJobOrder.getCompany(), applyJobOrder.getBranch(), applyJobOrder.getWorkPost());
        //获取人员钉钉ID
        DingDingPerson dingDingPerson = getDingDingUserId(applyJobOrder.getEmployee());
        String dingDingUserId = dingDingPerson.getDingDingUserId();
        //更新用户到对应的钉钉群
        userUpdate(list,dingDingUserId);
        //写入日志
        apesLoggerService.sendSynEvent("event:ir.logger.create", MapUtil.mapper("businessType", "DingDingPerson",
                "businessKey", dingDingPerson.getId(), "operate", "入职申请单号【 "+applyJobOrder.getId()+" 】更新人员钉钉部门信息", "workPostName",null,"operator_id", 1));
        //更新人员考勤组
        String groupId = findGroupByBranchOrEmployee(applyJobOrder.getEmployee(), applyJobOrder.getBranch());
        if (groupId != null) updateUserGroup(groupId,dingDingUserId);
        //如果入职的员工岗位是店长或者店长（驻店股东）设置为入职部门群的主管
        if (applyJobOrder.getWorkPost().getId().equals("0000016") || applyJobOrder.getWorkPost().getId().equals("0000752")){
            List<Long> branchDingDing = getBranchDingDing(applyJobOrder.getBranch());   //根据部门获取对应的钉钉群
            for (Long b : branchDingDing) {
                String zgByDept = getZGByDept(String.valueOf(b));   //获取该部门主管
                if (!zgByDept.equals("")) {
                    //此入职员工非该部门的主管拼接
                    if (!zgByDept.contains(dingDingUserId)) {
                        zgByDept = zgByDept + "|" + dingDingUserId;
                        updateDeptByZG(b, zgByDept);//执行更新部门主管操作
                    }
                }
                if (zgByDept.equals("")) updateDeptByZG(b,dingDingUserId);  //部门主管列表为空直接更新当前入职员工为钉钉部门主管
            }
        }
    }

    //调动申请单
    @OutboxSubscriber(id = "local:hrDingDingDeptService.transferDingDing", name = "调动申请单,进入对应的钉钉群")
    public void transferDingDing(OutboxPayloadWrapper outboxPayloadWrapper) {
        JSONObject object = JSONObject.parseObject(outboxPayloadWrapper.getPayload());
        List<TransferApplicationItem> item = itemService.findById(object.getInteger("id"));
        item.stream().forEach(itemzz -> {
            //根据调动单的运营模式公司部门岗位信息查找对应的钉钉部门
            List<Long> departments = getDingDingIds(itemzz.getTransferUid().getCompany().getParty().getCorporate().getOperation(),
                    itemzz.getTransferUid().getCompany(), itemzz.getBranchAfter(), itemzz.getWorkPostAfter());
//            String userDingDingId = itemzz.getTransferUid().getParty().getPerson().getDingDingUserId(); //获取当前调动单人员的钉钉ID


            DingDingPerson dingDingPerson = getDingDingUserId(itemzz.getTransferUid());
            String userDingDingId = dingDingPerson.getDingDingUserId();//获取人员钉钉ID

            //判断 钉钉ID是否存在钉钉后台有效性，为true说明不存在 直接跳过
            if (getUserValid(userDingDingId)) return;

            List<Long> oldDepartments = getUser(userDingDingId);    //获取原来的钉钉群ID
            String sType = itemzz.getTransferApplications().getHrTransferType().getId();    //获取调动类型
            if (sType.equals("000102")){
                //调动单 更新到新的钉钉群组
                userUpdate(departments,userDingDingId); //更新用户到对应的钉钉群
                //写入日志
                apesLoggerService.sendSynEvent("event:ir.logger.create", MapUtil.mapper("businessType", "DingDingPerson",
                        "businessKey", dingDingPerson.getId(), "operate", "调动申请单号【 "+itemzz.getTransferApplications().getId()+" 】更新人员钉钉部门信息",
                        "workPostName",null, "operator_id", 1));
                //更新人员考勤组
                String groupId = findGroupByBranchOrEmployee(itemzz.getTransferUid(), itemzz.getBranchAfter());
                if (groupId != null) updateUserGroup(groupId,userDingDingId);
                //员工调动后的岗位是店长或者店长（驻店股东）设置为调动后部门群的主管
                if (itemzz.getWorkPostAfter().getId().equals("0000016") || itemzz.getWorkPostAfter().getId().equals("0000752")){
                    List<Long> branchDingDing = getBranchDingDing(itemzz.getBranchAfter());   //根据部门获取对应的钉钉群
                    for (Long b : branchDingDing) {
                        String zgByDept = getZGByDept(String.valueOf(b));
                        if (!zgByDept.equals("")){
                            //根据主管列表判断当前的ID是否已经存在（存在为已经是主管的情况） 取反结果集为不存在的情况
                            if (!(zgByDept.contains("|" + userDingDingId) || zgByDept.contains(userDingDingId + "|") || zgByDept.contains(userDingDingId))){
                                updateDeptByZG(b,zgByDept + "|" + userDingDingId);
                            }
                        }
                        if (zgByDept.equals("")) updateDeptByZG(b,userDingDingId);//执行更新部门主管操作 (当前更新的部门没有主管情况下直接将当前人更新为主管)
                    }
                }
                //员工调动前的岗位是店长或者店长（驻店股东） 调动后的岗位非店长或者店长（驻店股东）取消当前部门群的主管 (降职情况)
                if ((itemzz.getWorkPost().getId().equals("0000016")&&!itemzz.getWorkPostAfter().getId().equals("0000016")) ||
                        (itemzz.getWorkPost().getId().equals("0000752")&&!itemzz.getWorkPostAfter().getId().equals("0000752")) ){
                    List<Long> branchDingDing = getBranchDingDing(itemzz.getBranch());   //根据部门获取对应的钉钉群
                    branchDingDing.forEach(b ->{
                        String zgByDept = getZGByDept(String.valueOf(b));
                        if (!zgByDept.equals("")){    //获取该部门的主管列表不为空 剔除当前员工在部门群的主管
                            if (zgByDept.contains("|" + userDingDingId)){
                                zgByDept = zgByDept.replaceAll("\\|" + userDingDingId,"");
                            } else if (zgByDept.contains(userDingDingId + "|" )){
                                zgByDept = zgByDept.replaceAll(userDingDingId + "\\|" ,"");
                            } else if (zgByDept.contains(userDingDingId)){
                                zgByDept = zgByDept.replaceAll(userDingDingId,"");
                            }
                        }
                        if (zgByDept.equals("")) zgByDept = "|"; //如果zgByDept 为空说明剔除或本身获取就是空，需要传 一个 | 清空该部门的主管
                        updateDeptByZG(b,zgByDept);//执行更新部门主管操作
                    });
                }
                //更新用户信息
//                updateDingDingUser(itemzz.getTransferUid(),userDingDingId);
                updateDingDingUserPosition(itemzz.getBranchAfter().getName() + "【" + itemzz.getWorkPostAfter().getName() + "】",userDingDingId);
            }else if (sType.equals("000103")){
                //支援单 更新到新的钉钉群组 不更新用户信息
                //原来的钉钉群和支援后的钉钉群组合
                List<Long> newDepartments = Stream.of(departments, oldDepartments)
                        .flatMap(Collection::stream)
                        .distinct()
                        .collect(Collectors.toList());
                userUpdate(newDepartments,userDingDingId);//更新用户到对应的钉钉群
                apesLoggerService.sendSynEvent("event:ir.logger.create", MapUtil.mapper("businessType", "DingDingPerson",
                        "businessKey", dingDingPerson.getId(), "operate", "支援申请单号【 "+itemzz.getTransferApplications().getId()+" 】更新人员钉钉部门",
                        "workPostName",null,"operator_id", 1));
            }
        });
    }

    @OutboxSubscriber(id = "local:hrDingDingDeptService.restoreDingDing", name = "终止申请单,还原钉钉群")
    public void restoreDingDing(OutboxPayloadWrapper outboxPayloadWrapper) {
        JSONObject object = JSONObject.parseObject(outboxPayloadWrapper.getPayload());
        List<TransferApplicationItem> item = itemService.findById(object.getInteger("id"));
        item.stream().forEach(itemzz ->{
            DingDingPerson dingDingPerson = getDingDingUserId(itemzz.getTransferUid());
            String userDingDingId = dingDingPerson.getDingDingUserId();//获取人员钉钉ID

            //判断 钉钉ID是否存在钉钉后台有效性，为true说明不存在 直接跳过
            if (getUserValid(userDingDingId)) return;

//            String userDingDingId = itemzz.getTransferUid().getParty().getPerson().getDingDingUserId();
            // 同步钉钉部门使用
            //根据调动前运营模式公司部门岗位查找对应的钉钉部门
            List<Long> departments = getDingDingIds(itemzz.getTransferUid().getCompany().getParty().getCorporate().getOperation(),
                    itemzz.getTransferUid().getCompany(), itemzz.getBranch(), itemzz.getWorkPost());
            //更新到对应的群
            userUpdate(departments,userDingDingId);
            if(item.get(0).getTransferApplications().getHrTransferType().getDescription().equals("调动")){
                //写入日志
                apesLoggerService.sendSynEvent("event:ir.logger.create", MapUtil.mapper("businessType", "DingDingPerson",
                        "businessKey", dingDingPerson.getId(), "operate", "终止调动申请单号"+itemzz.getTransferApplications().getId()+"更新人员钉钉部门信息",
                        "workPostName",null, "operator_id", 1));

                //更新人员考勤组(调动情况下才需要更新考勤组)
                String groupId = findGroupByBranchOrEmployee(itemzz.getTransferUid(), itemzz.getBranch());
                if (groupId != null) updateUserGroup(groupId,userDingDingId);
                //还原调动单，如果是店长或者店长（驻店股东）设置成部门群的主管
                if (itemzz.getWorkPost().getId().equals("0000016") || itemzz.getWorkPost().getId().equals("0000752")){
                    List<Long> branchDingDing = getBranchDingDing(itemzz.getBranch());   //根据部门获取对应的钉钉群
                    for (Long b : branchDingDing) {
                        String zgByDept = getZGByDept(String.valueOf(b));//获取原来部门群的主管
                        if (!zgByDept.equals("")){
                            //判断原来部门的主管列表是否有当前员工的若没有进行拼接
                            if (!zgByDept.contains(userDingDingId)){
                                updateDeptByZG(b,zgByDept + "|" + userDingDingId);//执行更新部门主管操作（原来部门群主管列表加上当前员工）
                            }
                        }
                        if (zgByDept.equals("")) updateDeptByZG(b,userDingDingId);  //主管列表为空将当前人员设置为主管
                    }
                }
                //更新用户信息
//                updateDingDingUser(itemzz.getTransferUid().getjo,userDingDingId);
                updateDingDingUserPosition(itemzz.getBranch().getName() + "【" + itemzz.getWorkPost().getName() + "】",userDingDingId);
            }else if(item.get(0).getTransferApplications().getHrTransferType().getDescription().equals("支援")){
                //写入日志
                apesLoggerService.sendSynEvent("event:ir.logger.create", MapUtil.mapper("businessType", "DingDingPerson",
                        "businessKey", dingDingPerson.getId(), "operate", "支援申请单号【 "+itemzz.getTransferApplications().getId()+" 】终止或支援结束更新人员钉钉部门信息",
                        "workPostName",null,"operator_id", 1));
            }

        });
    }

    //调动申请单
    @OutboxSubscriber(id = "local:hrDingDingDeptService.transferDingDingForFee", name = "计费支援申请单生效，进入对应的钉钉群")
    public void transferDingDingForFee(OutboxPayloadWrapper outboxPayloadWrapper) {
        JSONObject object = JSONObject.parseObject(outboxPayloadWrapper.getPayload());
        SupportApplicationItem item = supportApplicationItemRepository.findOne(object.getString("id"));

        //根据调动单的运营模式公司部门岗位信息查找对应的钉钉部门
        List<Long> departments = getDingDingIds(item.getSupportUid().getCompany().getParty().getCorporate().getOperation(),
                item.getSupportUid().getCompany(), item.getBranchAfter(), item.getWorkPostAfter());

        DingDingPerson dingDingPerson = getDingDingUserId(item.getSupportUid());
        String userDingDingId = dingDingPerson.getDingDingUserId();//获取人员钉钉ID

        //判断 钉钉ID是否存在钉钉后台有效性，为true说明不存在 直接跳过
        if (getUserValid(userDingDingId)) return;

        List<Long> oldDepartments = getUser(userDingDingId);    //获取原来的钉钉群ID

        //支援单 更新到新的钉钉群组 不更新用户信息
        //原来的钉钉群和支援后的钉钉群组合
        List<Long> newDepartments = Stream.of(departments, oldDepartments)
                .flatMap(Collection::stream)
                .distinct()
                .collect(Collectors.toList());
        //更新用户到对应的钉钉群
        userUpdate(newDepartments,userDingDingId);

        //日志写入
        apesLoggerService.sendSynEvent("event:ir.logger.create", MapUtil.mapper("businessType", "DingDingPerson",
                "businessKey", dingDingPerson.getId(), "operate", "计费支援申请单号【 "+item.getSupportApplication().getId()+" 】生效更新人员钉钉部门",
                "workPostName",null,"operator_id", 1));

    }

    @OutboxSubscriber(id = "local:hrDingDingDeptService.restoreDingDingForFee", name = "计费支援单申请单，支援结束还原钉钉群")
    public void restoreDingDingForFee(OutboxPayloadWrapper outboxPayloadWrapper) {
        JSONObject object = JSONObject.parseObject(outboxPayloadWrapper.getPayload());

        SupportApplicationItem item = supportApplicationItemRepository.findOne(object.getString("id"));

        DingDingPerson dingDingPerson = getDingDingUserId(item.getSupportUid());

        //获取人员钉钉ID
        String userDingDingId = dingDingPerson.getDingDingUserId();

        //判断 钉钉ID是否存在钉钉后台有效性，为true说明不存在 直接跳过
        if (getUserValid(userDingDingId)) return;

        //根据调动前运营模式公司部门岗位查找对应的钉钉部门
        List<Long> departments = getDingDingIds(item.getSupportUid().getCompany().getParty().getCorporate().getOperation(),
                item.getSupportUid().getCompany(), item.getBranch(), item.getWorkPost());
        //更新到对应的群
        userUpdate(departments,userDingDingId);

        //写入日志
        apesLoggerService.sendSynEvent("event:ir.logger.create", MapUtil.mapper("businessType", "DingDingPerson",
                "businessKey", dingDingPerson.getId(), "operate", "计费支援申请单号【 "+item.getSupportApplication().getId()+" 】支援结束更新人员钉钉部门信息",
                "workPostName",null,"operator_id", 1));
    }

    /**
     * 根据人员或者行政部门找到对应的考勤组ID
     * 优先使用人员去找到对应的考勤组ID,若人员没找到,使用行政部门去找考勤组ID
     * @param employee 人员
     * @param branch 行政部门
     * @return 考勤组ID
     */
    public String findGroupByBranchOrEmployee(Employee employee,Branch branch){
        String groupId = null;
        List<SimpleGroupDetail> byEmployee = simpleGroupDetailRepository.findByEmployee(employee);
        if (byEmployee.size()!=0){
            groupId = byEmployee.get(0).getSimpleGroup().getGroupId();
        }
        if (groupId == null){
            List<SimpleGroupDetail> byBranch = simpleGroupDetailRepository.findByBranch(branch);
            if (byBranch.size()!=0){
                groupId = byBranch.get(0).getSimpleGroup().getGroupId();
            }
        }
        return groupId;
    }

    /**
     * 更新人员考勤组
     * @param groupId 考勤组ID
     * @param userId 对应人员的钉钉ID
     */
    public void updateUserGroup(String groupId,String userId){
        dingService.groupMemberUpdate(dingDingToken.getAccessToken(),groupId,userId);
    }

    @OutboxSubscriber(id = "local:hrDingDingDeptService.doneCreateDingDingUser", name = "确认报道，添加钉钉用户")
    public void doneCreateDingDingUser(OutboxPayloadWrapper outboxPayloadWrapper) {
        JSONObject object = JSONObject.parseObject(outboxPayloadWrapper.getPayload());
        Employee employee = employeeRepository.findOne(object.getString("empId"));
        ApplyJobOrder applyJobOrder = applyJobOrderRepository.findOne(object.getString("applyId"));
        employee.getParty().getPerson().setDingDingUserId(createDingDingUser(employee,applyJobOrder));
    }

    /**
     * 删除钉钉用户
     * @param userId
     * @return
     * @throws
     */
    public String deleteDingDingUser(String userId){

        //获取 accessToken
        String accessToken = dingDingToken.getToken();
//        String userId = employee.getParty().getPerson().getDingDingUserId();
//        String userId = getDingDingUserId(employee);//获取人员钉钉ID
//        if (userId==null)throw new RuntimeException("系统里没有对应的钉钉ID.不能删除!");
        OapiUserDeleteResponse response = dingService.deleteUser(accessToken,userId);
        if (response.getErrcode()!=0 && response.getErrcode() != 60121){
            throw new RuntimeException("删除钉钉用户失败!"+  response.getErrmsg());
        }
        return response.getErrmsg();
    }

    /**
     * 更新钉钉用户信息（调动和支援）
     */
    public void updateDingDingUserPosition(String position,String userId){
        OapiUserUpdateRequest request = new OapiUserUpdateRequest();
        request.setPosition(position);
        request.setUserid(userId);
        OapiUserUpdateResponse response = dingService.updateUser(request,dingDingToken.getAccessToken());
        if (response.getErrcode()!=0){
            throw new RuntimeException("同步钉钉用户失败!" + response.getErrmsg());
        }
    }

    /**
     * 更新钉钉用户信息
     * @param employee 员工资料
     */
//    public void updateDingDingUser(Employee employee,String userDingDingId) {
//        OapiUserUpdateRequest request = new OapiUserUpdateRequest();
//        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
//        //获取 accessToken
//        String accessToken = dingDingToken.getToken();
//        request.setUserid(userDingDingId);
//        String name = employee.getName();
//        String mobile = employee.getMobileNumber();
//        String jobName = employee.getJob().getName();//职位
//        Date entryDate = employee.getEntryDate();//入职时间
//        Date birthday = employee.getBirthday();//生日
//        String origin = employee.getOrigin();//工号
////        String degree = applyJobOrder.getDegree().getDescription();//学历
//
//        request.setName(name);
//        request.setMobile(mobile);
//        request.setPosition(jobName);
//        request.setJobnumber(origin);
//        JSONObject jsonObject = new JSONObject();
//        jsonObject.put("生日",formatter.format(birthday));
////        jsonObject.put("学历",degree);
//        jsonObject.put("hiredDate",entryDate.getTime());
//        request.setExtattr(jsonObject.toJSONString());
//        OapiUserUpdateResponse response = dingService.updateUser(request,accessToken);
//        if (response.getErrcode()!=0){
//            throw new RuntimeException("同步钉钉用户失败!" + response.getErrmsg());
//        }
//    }

    /**
     * 添加钉钉用户
     * @param employee
     * @return
     * @throws
     */
    public String createDingDingUser(Employee employee,ApplyJobOrder applyJobOrder) {
        OapiUserCreateRequest request = new OapiUserCreateRequest();
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
        //获取 accessToken
        String accessToken = dingDingToken.getToken();

        String name = employee.getName();
        String mobile = employee.getMobileNumber();
        String jobName = employee.getJob().getName();//职位
        Date entryDate = employee.getEntryDate();//入职时间
        Date birthday = employee.getBirthday();//生日
        String origin = employee.getOrigin();//工号
        String degree = applyJobOrder.getDegree().getDescription();//学历
        List<Long> departments = new ArrayList<>();
        departments.add(1L);
        List<Post> postLists =  postRepository.findAllByBranchAndWorkPost(employee.getWorkBranch(), employee.getPost());
        postLists.stream().forEach(post -> {
            if(post.getDingDingDeptId()!=null){
                String[] strings = post.getDingDingDeptId().split(";");
                for (String string : strings) {
                    departments.add(Long.valueOf(string));
                }
            }
        });

        request.setName(name);
        request.setMobile(mobile);
        request.setPosition(jobName);
        request.setJobnumber(origin);
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("生日",formatter.format(birthday));
        jsonObject.put("学历",degree);
        jsonObject.put("hiredDate",entryDate.getTime());
        request.setExtattr(jsonObject.toJSONString());
        request.setDepartment(JSON.toJSONString(departments));
        OapiUserCreateResponse response = dingService.createUser(request,accessToken);
        if (response.getErrcode()!=0){
            throw new RuntimeException("同步钉钉用户失败!" + response.getErrmsg());
        }
        return response.getUserid();
    }

}
